package cn.jsj.invite.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.MD5;
import cn.jsj.invite.dao.InvitationDao;
import cn.jsj.invite.dao.StudentDao;
import cn.jsj.invite.pojo.InvitationInfo;
import cn.jsj.invite.pojo.StudentEnt;
import cn.jsj.invite.service.InvitationService;
import cn.jsj.invite.service.PictureFileService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Service
@Slf4j
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class InvitationServiceImpl implements InvitationService {

    private final InvitationDao invitationDao;
    private final StudentDao studentDao;
    private final RedisTemplate<String, Serializable> redisTemplate;
    private final PictureFileService pictureFileService;

    //图片保存路径
//    @Value("${photo.save-path}")
//    private String photoSavePath;

    public InvitationServiceImpl(InvitationDao invitationDao, StudentDao studentDao, PictureFileService pictureFileService, RedisTemplate<String, Serializable> redisTemplate) {
        this.invitationDao = invitationDao;
        this.studentDao = studentDao;
        this.pictureFileService = pictureFileService;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public InvitationInfo getOneInvitationById(Integer id) {
        //取得帖子信息对象
        InvitationInfo invitationInfo = invitationDao.selectOneInvitationById(id);
        //获取帖子的竞争人数
        String key = MD5.create().digestHex16(invitationInfo.getTitle());
//        Long size = redisTemplate.opsForHyperLogLog().size(key);
        Long size = redisTemplate.opsForSet().size(key);
        assert size != null;
        invitationInfo.setCompetitionNumber(size.intValue());
        //格式化帖子队列和图片队列
        InvitationServiceImpl.invitationInfoDataFormat(Collections.singletonList(invitationInfo));
        return invitationInfo;
    }

    @Override
    public PageInfo<InvitationInfo> listInvitationByTagAndArea(String tag, Integer area, Integer pageNumber) {
        pageNumber = pageNumber != null ? pageNumber : 1;
        PageHelper.startPage(pageNumber, 15);
        List<InvitationInfo> invitationInfos = invitationDao.selectInvitationByTagAndArea(tag, area);
        invitationInfoDataFormat(invitationInfos);
        return new PageInfo<>(invitationInfos, 5);
    }

    @Override
    public PageInfo<InvitationInfo> listInvitationByArea(Integer area, Integer pageNumber) {
        pageNumber = (pageNumber != null || pageNumber.equals(0)) ? pageNumber : 1;
        PageHelper.startPage(pageNumber, 15);
        List<InvitationInfo> invitationInfos = invitationDao.selectInvitationByArea(area);
        invitationInfoDataFormat(invitationInfos);
        return new PageInfo<>(invitationInfos, 5);
    }

    @Override
    public StudentEnt getInvitationPublisherContactInfo(Integer studentId, Integer invitationId) {
        if (ObjectUtil.hasNull(studentId, invitationId)) {
            return null;
        }
        //获取帖子信息
        InvitationInfo invitationInfo = invitationDao.selectOneInvitationById(invitationId);
        //判断帖子是否存在
        if (invitationInfo == null) {
            return null;
        }

        //获取学生信息
        StudentEnt studentEnt = studentDao.selectOneStudentById(studentId);
        //判断学生是否存在
        if (studentEnt == null) {
            return null;
        }

        //统计帖子查看的人数+1，重复的不多次统计
        String key = MD5.create().digestHex16(invitationInfo.getTitle());
        //这里有返回值Long，成功添加1，重复0
//        redisTemplate.opsForHyperLogLog().add(key, studentEnt.getId());
        redisTemplate.opsForSet().add(key, studentEnt.getId().toString());
        //封装联系方式，并返回
        StudentEnt studentContact = new StudentEnt();
        studentContact.setPhone(studentEnt.getPhone());

        if (invitationInfo.getInvitationType().equals(4)) {
            studentContact.setMailbox("  --  ");
            studentContact.setWechatNumber("  --  ");
        } else {
            studentContact.setWechatNumber(studentEnt.getWechatNumber());
            studentContact.setMailbox(studentEnt.getMailbox());
        }
        return studentContact;
    }

    @Override
    @Transactional
    public Integer publishOneStudentInvitation(InvitationInfo info, MultipartFile[] photo) {
        if (info == null) {
            return 0;
        }
        //获取学生信息
        StudentEnt studentEnt = studentDao.selectOneStudentById(info.getInitiatorId());
        //如果获取不到学生信息，返回null
        if (studentEnt == null) {
            return 0;
        }

        //标记帖子是学生贴还是学生会帖
        info.setInitiatorIdentityId(studentEnt.getIdentityId());

        //控制换行符存入数据库
        info.setContext(info.getContext().replace("\n", "\r\n"));
        //对保存上传的图片，图片最多3张，图片名UUID生成，1.存入数据库，2.作为保存后的图片名
        //存入数据库的图片名直接用逗号连接
        int length = photo.length;
        if (length != 0) {
//            ArrayList<String> photoNameArray = new ArrayList<>(3);
//            for (int i = 0; i < length; i++) {
//                //设置每一个文件的文件名，不包括扩展名
//                photoNameArray.set(i, UUID.fastUUID().toString());
//                try {
//                    //上传的文件的原始文件名
//                    String originalFilename = photo[i].getOriginalFilename();
////                    // 如果文件名为全路径，去掉前面的路径信息，例如IE，表单文件名为全路径
////                    int index = originalFilename.lastIndexOf('\\');
////                    if (index > 0 && index < originalFilename.length() - 1) {
////                        originalFilename = originalFilename.substring(index + 1);
////                    }
//                    //获取文件扩展名
//                    assert originalFilename != null;
//                    String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
//                    //将文件保存到指定位置，格式：保存路径+文件名+扩展名
//                    photo[i].transferTo(new File(photoSavePath + photoNameArray.get(i) + substring));
//                } catch (IOException e) {
//                    log.error("文件 " + photo[i].getOriginalFilename() + " 保存失败", e);
//                }
//            }
            //将生成的文件名用逗号连接，组装成存入数据库的格式
//            String join = String.join(",", ArrayUtil.toArray(photoNameArray, String.class));
//            info.setPicList(join);
            ArrayList<String> photoNameArray = new ArrayList<>();
            for (MultipartFile file : photo) {
                //此处相对路径 = 路径 + 文件名 + 扩展名，直接存即可
                String relativePath = pictureFileService.savePictureFile(file);
                photoNameArray.add(relativePath);
            }
            String join = String.join(",", ArrayUtil.toArray(photoNameArray, String.class));
            info.setPicList(join);
        }
        return invitationDao.insertOneStudentInvitation(info);
    }

    //将帖子的标签信息，图片信息，String做成集合。便于序列化后转为JSON数组
    static void invitationInfoDataFormat(List<InvitationInfo> invitationInfos) {
        if (invitationInfos == null){
            return;
        }
        invitationInfos.forEach(s -> {
            if (s.getPicList() != null) {
                s.setPics(Arrays.asList(s.getPicList().split(",")));
                s.setPicList(null);
            }
            if (s.getTagList() != null) {
                s.setTags(Arrays.asList(s.getTagList().split(",")));
                s.setTagList(null);
            }
        });
    }

}
